package com.bgi.cg.oss4j.provider.qiniu.service;

import cn.hutool.core.date.DateUtil;
import com.bgi.cg.api.AbstractOssService;
import com.bgi.cg.api.entity.OssResponse;
import com.bgi.cg.oss4j.common.factory.BeanFactory;
import com.bgi.cg.oss4j.common.util.OssUtil;
import com.bgi.cg.oss4j.provider._base.OssSupplierType;
import com.bgi.cg.oss4j.provider.qiniu.config.QiniuOssConfig;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.DownloadUrl;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.BucketInfo;
import com.qiniu.util.Auth;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.Date;
import java.util.concurrent.Executor;
import java.util.function.Function;

/**
 * @Description 七牛云
 * @Author Z.cg
 * @Date 2023/9/8
 * @Version 1.0
 **/
@Slf4j
public class QiniuOssService extends AbstractOssService {
    private final QiniuOssConfig config;
    private Auth auth;
    private UploadManager uploadManager;
    private BucketManager bucketManager;

    public QiniuOssService(QiniuOssConfig qiniuOssConfig, Executor pool) {
        super(pool);
        this.config = qiniuOssConfig;
        this.auth = Auth.create(qiniuOssConfig.getAccessKey(), qiniuOssConfig.getAccessKeySecret());
        Configuration configuration = new Configuration(Zone.autoZone());
        this.uploadManager = new UploadManager(configuration);
        this.bucketManager = new BucketManager(auth, configuration);
        if (qiniuOssConfig.isBucketAutoCreate()) {
            try {
                BucketInfo bucketInfo = bucketManager.getBucketInfo(qiniuOssConfig.getBucket());
            } catch (Exception exception) {
                try {
                    bucketManager.createBucket(qiniuOssConfig.getBucket(), Zone.autoZone().getRegion());
                } catch (QiniuException qiniuExceptione) {
                    log.error("【{}】创建bucket失败：{}", OssSupplierType.QINIU.name(), qiniuExceptione.getMessage());
                }
            }
        }
    }

    @Override
    public OssResponse upload(File file) {
        return upload(file, config.getBucket());
    }

    @Override
    public OssResponse upload(File file, String bucketName) {
        return upload(file, bucketName, OssUtil::generatePath);
    }

    @Override
    public OssResponse upload(File file, Function<File, String> fileKeyFunction) {
        return upload(file, config.getBucket(), fileKeyFunction);
    }

    @Override
    public OssResponse upload(File file, String bucketName, Function<File, String> fileKeyFunction) {
        valiConfigIsOk();
        String fileName = fileKeyFunction.apply(file);
        OssResponse ossResponse = OssResponse.builder().code("0").filePath(fileName).ossType(OssSupplierType.QINIU.name()).build();
        try {
            Response response = uploadManager.put(file, fileName, auth.uploadToken(bucketName));
            if (response.isOK()) {
                //DefaultPutRet putRet = Json.decode(response.bodyString(),DefaultPutRet.class);
                ossResponse.setOk();
            } else {
                ossResponse.setFail(response.error);
            }
        } catch (QiniuException exception) {
            log.error("【{}】OSS文件上传失败：{}", OssSupplierType.QINIU.name(), exception.getMessage());
            ossResponse.setFail(exception.getMessage());
        }
        return ossResponse;
    }

    @Override
    public OssResponse genPreviewUrl(String fileName) {
        return genPreviewUrl(fileName, config.getBucket());
    }

    @Override
    public OssResponse genPreviewUrl(String fileName, String bucketName) {
        OssResponse ossResponse = OssResponse.builder().code("0").build();
        DownloadUrl url = new DownloadUrl(config.getFileDomain(), false, fileName);
        Integer expireMs = BeanFactory.getOssConfig().getDownloadUrlExpireMs();
        Date expireTime = DateUtil.offsetSecond(new Date(), expireMs);
        try {
            String previewUrl = url.buildURL(auth, expireTime.getTime());
            ossResponse.setPreviewUrl(previewUrl);
        } catch (QiniuException exception) {
            log.error("【{}】OSS文件下载失败：{}", OssSupplierType.QINIU.name(), exception.getMessage());
            ossResponse.setFail(exception.response.getInfo());
        }
        return ossResponse;
    }

    @Override
    public OssResponse delete(String fileName) {
        return delete(fileName, config.getBucket());
    }

    @Override
    public OssResponse delete(String fileName, String bucketName) {
        OssResponse ossResponse = OssResponse.builder().code("0").build();
        try {
            bucketManager.delete(bucketName, fileName);
        } catch (QiniuException exception) {
            log.error("【{}】OSS文件删除失败：{}", OssSupplierType.QINIU.name(), exception.getMessage());
            ossResponse.setFail(exception.response.getInfo());
        }
        return ossResponse;
    }

    void valiConfigIsOk() {
        if (!config.configIsOk()) {
            throw new RuntimeException("未配置[accessKey,accessKeySecret,bucket,endPoint,region]值");
        }
    }
}
